-- UIAirShipExplore
-- Create by chendh
-- 天空之城飞艇探索特效界面

-- UIAirShipExplore继承自Layer
UIAirShipExplore = class("UIAirShipExplore", function()
    return cc.Layer:create();
end);

function UIAirShipExplore.create(eventInfo)
    return UIAirShipExplore.new(eventInfo);
end

local SCRAP_CLASS_ID = 10000;

-- 内部函数声明

-- 构造函数
function UIAirShipExplore:ctor(eventInfo)
    -- 初始化
    self:setName("UIAirShipExplore");
    local node = cc.CSLoader:createNode("layout/sky_city/AirShipExplore.csb");
    self:addChild(node);
    self.node = node;

    self.eventInfo = eventInfo;

    -- 注册事件处理回调函数
    self:registerEventCallback();

    -- 注册点击事件
    self:registerTouchEvent();

    -- 适配
    self:resize();

    -- 重绘
    self:redraw();
end

-- 适配
function UIAirShipExplore:resize()
    local node = self.node;

    -- CT居中并缩放至合适大小
    AlignM.alignToCenter(node, "CT");

    local islandNode = findChildByName(node, "island");
    --local airShipNode = findChildByName(node, "island/island2/airship");
    local skyNode    = findChildByName(node, "sky");
    local cloudNode  = findChildByName(node, "floating_cloud");
    local bgPanel    = findChildByName(node, "bg");

    local w = AlignM.frameSize.width;
    local h = AlignM.frameSize.height;

    islandNode:setPosition(cc.p(0, h / DESIGN_HEIGHT * islandNode:getPositionY()));
    islandNode:setScale(math.min(w / DESIGN_WIDTH, h / DESIGN_HEIGHT));

    -- 背景用于吸收点击的容器设置跟界面等大
    bgPanel:setContentSize(cc.size(w, h));

    --airShipNode:setScale(math.min(w / DESIGN_WIDTH, h / DESIGN_HEIGHT));
    --airShipNode:setPosition(w / DESIGN_WIDTH * airShipNode:getPositionX(), h / DESIGN_HEIGHT * airShipNode:getPositionY());

    skyNode:setPosition(cc.p(w / 2, h / 2));
    skyNode:setScaleX(w / DESIGN_WIDTH);
    skyNode:setScaleY(h / DESIGN_HEIGHT);

    cloudNode:setPosition(cc.p(w / 2, 0));
    cloudNode:setScale(math.min(w / DESIGN_WIDTH, h / DESIGN_HEIGHT));
end

-- 绘制界面
function UIAirShipExplore:redraw()
    -- 浮岛悬浮
    self:playIslandFluctuate();

    -- 开始播放探索特效
    self:playExploreEffect1();

    -- 云层漂浮效果
    self:playFloatingCloudEffect();

    -- 背景特效
    self:playBgEffect();

    -- 遮挡物绘制
    self:redrawObstacle();
end

-- 遮挡物绘制
function UIAirShipExplore:redrawObstacle()
    local obstacle = findChildByName(self.node, "island/island2/obstacle");
    local iconPathArr = {
        getSkyCityCombatIslandsIconPath("public/broken_pavilion"),
        getSkyCityCombatIslandsIconPath("public/broken_sculpture"),
        getSkyCityCombatIslandsIconPath("temple/broken_airship"),
    };
    local path = iconPathArr[math.random(#iconPathArr)];

    obstacle:loadTexture(path, 1);
end

-- 播放浮岛悬浮效果
function UIAirShipExplore:playIslandFluctuate()
    local islandNode = findChildByName(self.node, "island");
    local island1 = findChildByName(islandNode, "island1");
    local island2 = findChildByName(islandNode, "island2");
    local island3 = findChildByName(islandNode, "island3");
    local island4 = findChildByName(islandNode, "island4");

    -- 岛屿往不同方向悬浮移动
    playFluctuateAnima(island1, 1.5, -5);
    playFluctuateAnima(island2, 1.5, 5);
    playFluctuateAnima(island3, 1.5, -5);
    playFluctuateAnima(island4, 1.5, 5);
end

-- 播放开始探索特效第一部分
function UIAirShipExplore:playExploreEffect1()
    local airShipNode = findChildByName(self.node, "island/island2/airship");

    -- 飞艇悬浮
    playFluctuateAnima(airShipNode, 0.1, 1);

    local w = AlignM.frameSize.width;
    local h = AlignM.frameSize.height;

    -- 飞船从右侧飞入
    AudioM.playFx("airship_fly");
    local activedShip = NewAirShipM.getActiveAirShip();
    airShipNode:setPositionX(airShipNode:getPositionX() + w);

    -- 创建飞船
    createAirShip(airShipNode, activedShip);

    -- 检查是否已经收到奖励信息
    local function checkBonus()
        self.slimeOut = true;

        -- 尝试开始第二部分的特效
        self:tryToEffect2();
    end

    -- 冈布奥跳到浮岛上，并且跑出屏幕外面
    local function slimeEffect()
        -- 创建冈布奥图片
        local army = SkyCombatM.getSkyArmy();
        local petId = 1;

        if #army > 0 then
            petId = army[math.random(#army)];
        end
        local icon = findChildByName(self.node, "island/island2/pet");
        icon:loadTexture(getMiddleHeroIconPath(PetM.getDefaultIcon(petId)));
        icon:setScale(0.8);
        icon:setVisible(true);
        icon:setOpacity(0);
        self.pet = icon;

        -- 冈布奥图片出现在浮岛上，并且跑出屏幕外面

        -- 将锚点设置在底部居中，方便播放动画
        icon:setAnchorPoint(cc.p(0.5, 0));
        icon:setPositionY(icon:getPositionY() - icon:getContentSize().height / 2);

        -- 淡入并且跑出屏幕外
        local fadeIn = cc.FadeIn:create(1);
        local moveBy = cc.MoveBy:create(2, cc.p(-w, 0));
        local delay = cc.DelayTime:create(0.1);

        -- 烟尘光效
        local function createDustEffect()
            local _, effect = playEffect(icon, 1807, 800, 40);
            effect:setScaleX(-1 * effect:getScaleX());
            effect:setLocalZOrder(-1);
            icon.effect = effect;
        end

        icon:runAction(cc.Sequence:create(fadeIn, cc.CallFunc:create(createDustEffect), moveBy, delay, cc.CallFunc:create(checkBonus)));
    end

    -- 飞艇飞入屏幕
    local moveBy1 = cc.EaseOut:create(cc.MoveBy:create(1, cc.p(-1 * w - 20, 0)), 2.5);
    local moveBy2 = cc.MoveBy:create(0.1, cc.p(20, 0));
    airShipNode:runAction(cc.Sequence:create(moveBy1, cc.CallFunc:create(slimeEffect), moveBy2));
end

-- 播放开始探索特效第二部分
function UIAirShipExplore:playExploreEffect2()
    local island2Node = findChildByName(self.node, "island/island2");
    local airShipNode = findChildByName(self.node, "island/island2/airship");
    local petIcon = self.pet;
    local bonus = {};
    local treasureInfo = self.treasureInfo;

    local w = AlignM.frameSize.width;
    local h = AlignM.frameSize.height;

    -- 将奖励数据特殊处理一下
    -- 古遗迹碎片需要分成多份
    for _, info in pairs(self.bonus) do
        if SCRAP_CLASS_ID == info[2] then
            -- 根据浮岛的等级，计算古遗迹碎片份数
            local exploreLevel = self.eventInfo["explore_level"] or 0;
            local baseCount = FormulaM.invoke("CALC_RELIC_FRAGMENT_BASE_COUNT", exploreLevel);
            local total = 0;

            repeat
                local amount = baseCount;
                if info[3] - total < baseCount * 2 then
                    amount = info[3] - total;
                end
                total = total + amount;

                table.insert(bonus, {info[1], info[2], amount});
            until total >= info[3];
        else
            table.insert(bonus, info);
        end
    end

    -- 播放奖励特效
    local function bonusEffect()
        if petIcon.effect then
            petIcon.effect:removeFromParent();
        end

        local function createTextFunc(color, str)
            local text = ccui.Text:create();
            text:setFontName(getLocFontName());
            text:setFontSize(36);
            text:setString(str);
            text:setTextColor(color);
            text:setAnchorPoint(cc.p(0.5, 0.5));
            local outlineColor = TextStyleM.TEXT_COLOR_DARK_BROWN;
            local kerning = -4;
            if getLang() == "th" then
                kerning = 0;
            end
            text:enableOutline(cc.c4b(outlineColor[1], outlineColor[2], outlineColor[3], 255), 2);
            text:enableShadow(TextStyleM.TEXT_OUTLINE_COLOR_DARK, cc.size(3, -3));
            text:getVirtualRenderer():setAdditionalKerning(getLocKerning() + kerning);

            return text;
        end

        -- 奖励飞到飞船
        local index = 1;
        local function bonusFlyToAirShip( ... )
            -- 创建奖励图标节点
            local info = bonus[index];

            if not info then
                return;
            end

            local icon = ccui.ImageView:create();
            local name;
            if info[1] == 1 then
                -- 道具
                icon:loadTexture(getItemIconPath(ItemM.query(info[2], "icon")));
                name = ItemM.query(info[2], "name");
            else
                -- 属性
                icon:loadTexture(getLargeAttribIconPath(info[2]));
                name = FieldsM.getFieldName(info[2]);
            end

            icon:setPosition(petIcon:getPositionX(), petIcon:getPositionY() + petIcon:getContentSize().height / 2);
            icon:setScale(0.8);

            island2Node:addChild(icon);

            -- 奖励图标飞跃到飞船上
            local jumpTo = cc.JumpTo:create(0.4, cc.p(airShipNode:getPositionX(), airShipNode:getPositionY()), 100, 1);
            icon:runAction(cc.Sequence:create(jumpTo, cc.CallFunc:create(function ()
                icon:removeFromParent();
            end)));
            AudioM.playFx("throwing");

            -- 飞船上飘起奖励描述文本
            local notifyText = string.format(getLocStr("gain_scout_items"), name, info[3]);
            local text = createTextFunc(TextStyleM.TEXT_COLOR_BRIGHT_YELLOW, notifyText);
            local curScale = text:getScale();
            text:setScale(0.8 * curScale);
            local scaleUp = cc.ScaleTo:create(0.2, 1.2 * curScale);
            local scaleDown = cc.ScaleTo:create(0.15, 1.0 * curScale);
            local move = cc.MoveBy:create(1.0, cc.p(0, 50));
            local delay = cc.DelayTime:create(0.5);
            local fadeOut = cc.FadeOut:create(0.5);
            local callFunc2 = cc.CallFunc:create(function()
                text:removeFromParent();
            end);

            --text:setPosition(airShipImg:getContentSize().width / 2, airShipImg:getContentSize().height / 2);
            airShipNode:addChild(text);
            text:setName("bonusText" .. index);

            local action = cc.Sequence:create(scaleUp, scaleDown, cc.Spawn:create(move, cc.Sequence:create(delay, fadeOut)), callFunc2);
            text:runAction(action);

            index = index + 1;
            if index <= #bonus then
                performWithDelay(self, bonusFlyToAirShip, 0.4);
            end
        end

        bonusFlyToAirShip();

        -- 飞船飞出屏幕
        local function airShipFlyOut()
            petIcon:removeFromParent();
            -- 飞船节点翻转
            airShipNode:setScaleX(-1 * airShipNode:getScaleX());
            -- 文字不能翻转
            local textNode = airShipNode:getChildByName("bonusText" .. #bonus);
            if textNode then
                textNode:setScaleX(-1 * textNode:getScaleX());
            end
            -- 飞船飞走
            local moveBy1 = cc.MoveBy:create(1, cc.p(w, 0));
            airShipNode:runAction(cc.Sequence:create(moveBy1));

            performWithDelay(self, function ()
                self:endEffect();
            end, 1);
            AudioM.playFx("airship_fly");
        end

        performWithDelay(self, function ()
            if not self.treasureInfo then
                -- 冈布奥跳到飞船上
                local jumpTo = cc.JumpTo:create(0.3, cc.p(airShipNode:getPositionX(), airShipNode:getPositionY()), 100, 1);

                petIcon:runAction(cc.Sequence:create(jumpTo));

                performWithDelay(self, airShipFlyOut, 0.3);
            else
                -- 发现了宝藏
                self:palyTreatureEffect();
            end
        end, #bonus * 0.4 + 0.3);
    end

    -- 先设置冈布奥反向
    petIcon:setScaleX(-1 * petIcon:getScaleX());
    -- 冈布奥跑回屏幕内
    local moveBy = cc.MoveBy:create(2, cc.p(w, 0));
    petIcon:runAction(cc.Sequence:create(moveBy, cc.CallFunc:create(bonusEffect)));
    AudioM.playFx("explore");
end

-- 尝试开始第二部分的特效
function UIAirShipExplore:tryToEffect2()
    if not self.slimeOut or not self.bonus then
        return;
    end

    -- 第一部分播放完毕，并且收到了奖励信息，开始播放第二部分
    self:playExploreEffect2();
end

-- 冈布奥跳跃
function UIAirShipExplore:playSlimeJump(petNode)
    local scaleX = petNode:getScaleX();
    local scaleY = petNode:getScaleY();
    local scaleDown = cc.ScaleTo:create(0.2, scaleX, 0.8 * scaleY);
    local scaleUp = cc.ScaleTo:create(0.1, scaleX, scaleY);
    local moveUp = cc.EaseOut:create(cc.MoveBy:create(0.2, cc.p(0, 60)), 2.5);
    local moveDown = cc.EaseIn:create(cc.MoveBy:create(0.2, cc.p(0, -60)), 2.5);

    petNode:runAction(cc.Sequence:create(scaleDown, scaleUp, moveUp, moveDown));

    return 0.7;
end

-- 播放发现宝藏特效
function UIAirShipExplore:palyTreatureEffect()
    -- 1. 冈布奥原地跳一下，头上出现感叹号
    -- 2. 屏幕往左移，看到神殿建筑
    -- 3. 弹出提示框

    -- 转向
    self.pet:setScaleX(-1 * self.pet:getScaleX());

    -- 冈布奥跳跃
    local delay = self:playSlimeJump(self.pet);
    performWithDelay(self, function() AudioM.playFx("slime_jump"); end, 0.5);

    local moveDelay = 3;
    -- 出现感叹号
    performWithDelay(self, function ()
        local icon = ccui.ImageView:create();
        icon:loadTexture(getWorkshopIconPath("guide/bubble2"));
        icon:setPosition(cc.p(self.pet:getContentSize().width / 2 + 70, self.pet:getContentSize().height / 2 + icon:getContentSize().height / 2 + 10));
        icon:setScale(0.8);

        self.pet:addChild(icon);

        local icon2 = ccui.ImageView:create();
        icon2:loadTexture(getWorkshopIconPath("guide/exclamation_mark"));
        icon2:setPosition(cc.p(icon:getContentSize().width / 2, icon:getContentSize().height / 2));
        icon2:setScale(0.8);
        icon:addChild(icon2);

        -- 屏幕移动
        local w = cc.Director:getInstance():getOpenGLView():getFrameSize().width;
        local moveBy1 = cc.EaseInOut:create(cc.MoveBy:create(moveDelay, cc.p(1.3 * w, 0)), 2.5);
        local moveBy2 = cc.EaseInOut:create(cc.MoveBy:create(moveDelay, cc.p(-1.3 * DESIGN_WIDTH, 0)), 2.5);
        local moveBy3 = cc.EaseInOut:create(cc.MoveBy:create(moveDelay, cc.p(1.3 * w, 0)), 2.5);
        local moveBy4 = cc.EaseInOut:create(cc.MoveBy:create(moveDelay, cc.p(1.3 * w, 0)), 2.5);

        local skyNode = findChildByName(self.node, "sky");
        local islandNode = findChildByName(self.node, "island");
        local cloudNode  = findChildByName(self.node, "floating_cloud");
        local skyBg = findChildByName(self.node, "sky/sky_bg");

        -- 沿抛物线往上飞
        local function moveCloudPos()
            -- 调整云层节点坐标
            cloudNode:setPosition(-1 * w, 0);

            -- 重现开始云层悬浮效果
            self:playFloatingCloudEffect();
        end

        local callFunc = cc.CallFunc:create(moveCloudPos);

        skyNode:runAction(cc.Sequence:create(moveBy1, callFunc));
        skyBg:runAction(cc.Sequence:create(moveBy2));
        islandNode:runAction(cc.Sequence:create(moveBy3));
        cloudNode:runAction(cc.Sequence:create(moveBy4));

    end, delay);

    delay = delay + moveDelay;

    -- 播放神殿光效
    if self.treasureInfo then
        local node = findChildByName(self.node, "CT/treasure_name");
        performWithDelay(node, function ()
            -- 提示发现了神殿
            self:playTreatureNameFlyIn();

            local skyImg = findChildByName(self.node, "sky/sky_bg");
            skyImg:setTouchEnabled(true);
            local function onBgClick(sender, eventType)
                if eventType == ccui.TouchEventType.ended then
                    self:endEffect();
                end
            end
            skyImg:addTouchEventListener(onBgClick);
        end, delay);
    end
end

-- 神殿名称飞入
function UIAirShipExplore:playTreatureNameFlyIn()
    local node = findChildByName(self.node, "CT/treasure_name");
    local treasureId = self.treasureInfo["treasure_id"];
    local templeName = SkyResourceM.querySkyTreasure(treasureId, "name");
    node:setString(templeName);

    local fontSize = 80 * getLocFontSizeMulti();
    local textMask = "images/ui/text_mask/text_mask.png";

    -- 生成艺术字并旋转飞入
    genArtWordAndRotateFlyIn(node, fontSize, textMask);
end

-- 结束
function UIAirShipExplore:endEffect()
    -- 发现宝藏
    --[[if self.treasureInfo then
        self.node:setVisible(false);
        local skyCity = UIMgr.getCurrentScene():getFormByName("UISkyCity");
        if skyCity then
            skyCity:setVisible(true);
        end
    else]]
        -- 直接关闭掉界面
        UIMgr.getCurrentScene():removeFormByName("UIAirShipExplore");
    --end
end

-- 注册事件处理回调函数
function UIAirShipExplore:registerEventCallback()
    EventMgr.register("UIAirShipExplore", event.SKY_EXPLORE_BONUS, function(para)

        if para.index then
            local event = SkyExploreM.getExploreEvents()[para.index] or {};
            -- 处理的为对应返回的消息
            if event.pos ~= self.eventInfo.pos then
                return;
            end
        end

        self.bonus = para.bonus;

        if para.treasureInfo then
            self.treasureInfo = para.treasureInfo;
        end

        if para.bonus and type(para.bonus[1]) == "number" then
            self.bonus = { para.bonus };
        end

        if self.treasureInfo then
            local treasureId = self.treasureInfo["treasure_id"];
            local island4Node = findChildByName(self.node, "island/island4");
            island4Node:removeAllChildren();
            local node = cc.CSLoader:createNode(string.format("layout/sky_city/explore/Treasure%d.csb", treasureId));
            local effectNode1 = findChildByName(node, "island/effect1");
            local effectNode2 = findChildByName(node, "island/effect2");
            local effectNode3 = findChildByName(node, "island/effect3");
            node:setName("treasure");
            island4Node:addChild(node);
            self.effectNode = effectNode1;

            playEffect(effectNode1, 1818);
            playEffect(effectNode2, 1819);
            playEffect(effectNode3, 1820);
        end

        -- 尝试开始第二部分的特效
        self:tryToEffect2();
    end);

    -- 注册获得焦点的回调
    EventMgr.register("UIAirShipExplore", event.FOCUS_CHANGED, function(para)
        if para["get"] == "UIAirShipExplore" then
            UIMgr:getCurrentScene().topMenu:show(TOPMENU_FRAME_MONEY, TOPMENU_FRAME_RUINS_SCRAP, TOPMENU_FRAME_HEAD_AIRSHIP);
        elseif para["lose"] == "UIAirShipExplore" then

        end
    end);

    -- 界面析构后，需要清理下
    self:registerScriptHandler(function(eventType)
        if eventType == "exit" then
            EventMgr.removeAll("UIAirShipExplore");

            -- 显示天空之城界面及topmenu界面
            local skyCity = UIMgr.getCurrentScene():getFormByName("UISkyCity");
            if skyCity then
                skyCity:setVisible(true);
            end
        elseif eventType == "enter" then
            -- 隐藏天空之城界面及topmenu界面，以降低GL calls
            local skyCity = UIMgr.getCurrentScene():getFormByName("UISkyCity");
            if skyCity then
                skyCity:setVisible(false);
            end
        end
    end);
end

-- 注册点击事件
function UIAirShipExplore:registerTouchEvent()
    --[[local skyImg = findChildByName(self.node, "sky/sky_bg");
    skyImg:setTouchEnabled(true);
    local function onBgClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            self:endEffect();
        end
    end
    skyImg:addTouchEventListener(onBgClick);]]
end

-- 播放云层漂浮效果
function UIAirShipExplore:playFloatingCloudEffect()
    local floatingCloud = findChildByName(self.node, "floating_cloud");
    local w = AlignM.frameSize.width;
    local h = AlignM.frameSize.height;

    local function floatingCloudEffect()
        -- 随机出1或2朵云
        local cloudNum = math.random(2);

        for i = 1, cloudNum do
            local cloudImg = ccui.ImageView:create();
            cloudImg:loadTexture(getSkyCityPath("sky/floating_cloud" .. math.random(2)), 1);
            -- 随机初始个坐标
            cloudImg:setPosition(cc.p(w / -2 - 100, math.random(h)));

            floatingCloud:addChild(cloudImg);

            local i = 1;
            -- 随机抽取飞行方向
            if math.random(100) <= 50 then
                i = -1;
            end
            cloudImg:setPosition(cc.p(i * w / -2 + i * -100, math.random(60, 360)));

            -- 沿抛物线往上飞
            local function removeCloud()
                cloudImg:removeFromParent();
            end
            local jumpOut = cc.JumpBy:create(math.random(30, 50), cc.p(i * w * 2 + i * 200, 0), 0, 1);
            local callFunc = cc.CallFunc:create(removeCloud);
            cloudImg:runAction(cc.Sequence:create(jumpOut, callFunc));
        end

        -- 等一段时间后再来一次
        performWithDelay(floatingCloud, floatingCloudEffect, math.random(120));
    end

    performWithDelay(floatingCloud, floatingCloudEffect, math.random(5));
end

-- 背景浮云飘动
function UIAirShipExplore:playBgEffect()
    local bgParent = findChildByName(self.node, "sky");
    if not bgParent then
        return;
    end

    local w = cc.Director:getInstance():getOpenGLView():getFrameSize().width;
    local h = cc.Director:getInstance():getOpenGLView():getFrameSize().height;
    local function cloudEffect(node)
        local originX = node:getPositionX();
        local moveBy1 = cc.MoveBy:create(80, cc.p(w, 0));
        local callFunc = cc.CallFunc:create(function() node:setPositionX(originX); end);

        node:runAction(cc.RepeatForever:create(cc.Sequence:create(moveBy1, callFunc, moveBy1)));
    end

    -- 获取背景浮云节点
    local childs = bgParent:getChildren();
    for _, child in pairs(childs) do
        local name = child:getName();
        if string.startWith(name, "cloud") then
            performWithDelay(self.node, function()
                cloudEffect(child);
            end, math.random(1, 3));
        end
    end
end
